package com.tonicartos.superslim;

import java.util.Arrays;

/**
 * SECTION 缓存, 暂时置于此处, 稍后融合到SectionManager中
 */
public class SectionCache extends Object implements SectionLayoutManager.SectionDelegate {



    public static final int SECTION_INVALID_ID = -1;
    public static final int SECTION_CONTENT_ID = 0;

    /**
     * data结构： 前16位存 是否为section, 0为内容, 其它为section;
     * 后16位存 所在section的pos
     */
    private int[] mSectionCache;
    private SectionLayoutManager.SectionDelegate mDelegate;

    public SectionCache(SectionLayoutManager.SectionDelegate sd) {
        super();
        mDelegate = sd;
    }

    @Override
    public int getSection(int position) {
        buildExpendCache(position);

        generateSection(position);

        int data = mSectionCache[position];
        return sectionPref16(data);
    }

    private void generateSection(int position) {
        if (position < 0) {
            return;
        }
        int data = mSectionCache[position];
        if (isValidSectionData(data)) {
            return;
        }

        int section = mDelegate.getSection(position);
        if (SECTION_CONTENT_ID != section) {
            data = sectionBuild(section, position);
            mSectionCache[position] = data;
        } else {
            int nerb = position - 1;
            if (nerb < 0) nerb = 0;
            data = mSectionCache[nerb];
            if (isValidSectionData(data)) {
                data = sectionBuild(section, sectionSurf16(data));
            } else {
                int startSectionPos = findSection(nerb);
                int i = startSectionPos;
                mSectionCache[i] = sectionBuild(1, startSectionPos);
                for (i = startSectionPos + 1; i <= nerb; i++) {
                    mSectionCache[i] = sectionBuild(SECTION_CONTENT_ID, startSectionPos);
                }
                data = sectionBuild(section, startSectionPos);
            }
            mSectionCache[position] = data;
        }
    }

    private int findSection(int position) {
        while (position >= 0) {
            int data = mSectionCache[position];
            if (isValidSectionData(data)) {
                return sectionSurf16(data);
            }
            int section = mDelegate.getSection(position);
            if (SECTION_CONTENT_ID != section) {
                return position;
            } else {
                position --;
                continue;
            }
        }
        return 0;
    }

    @Override
    public int getColumnForSection(int position) {
        return mDelegate.getColumnForSection(position);
    }

    /**
     * 清除缓存
     */
    public void clearCache() {
        if (null != mSectionCache) {
            Arrays.fill(mSectionCache, -1);
        }
    }

    public static int sectionPref16(int data) {
        data = data & 0xffff0000;
        data = data >> 16;
        return data;

    }

    public static int sectionSurf16(int data) {
        return data & 0x0000ffff;
    }

    public static int sectionBuild(int pre, int surf) {
        pre = pre << 16; pre = pre & 0xffff0000;
        surf = surf & 0x0000ffff;
        return pre | surf;
    }

    public static boolean isValidSectionData(int data) {
        return SECTION_INVALID_ID != data;
    }

    private void buildExpendCache(int position) {
        int size = null != mSectionCache ? mSectionCache.length : 0;
        if (position + 1 > size) {
            size = 2 * (position + 1);
            if (size < 10) size = 10;
            int[] newCache = new int[size];
            Arrays.fill(newCache, SECTION_INVALID_ID);

            if (null != mSectionCache) {
                System.arraycopy(mSectionCache, 0, newCache, 0, mSectionCache.length);
            }
            mSectionCache = newCache;
        }
    }

    public int getSectionPosition(int position) {
        buildExpendCache(position);

        generateSection(position);

        int data = mSectionCache[position];
        return sectionSurf16(data);
    }
}
